#!~/opt/Z261/bin/python
#
# Testing the bug repository
#

import os, sys
from Testing import ZopeTestCase
from AccessControl.SecurityManagement import newSecurityManager
import AccessControl

# local imports
from Products import DDBug
from Products.DDBug.interfaces import IBugRepository, IBug
from Products.DDBug import permissions
from Products.DDBug import bug


# some global vars
_standard_permissions = ZopeTestCase._standard_permissions

# some helper objects
class DummyResponse:
    redirectedTo = None

    def redirect(self, someurl):
        self.redirectedTo = someurl

class DummyRequest:
    """ to verify how certain classes are using the request """
    # Leo:
    # I should hack ZopeTestCase to include more introspectable
    # request and response objects, so as not to need this.
    def __init__(self):
        self.RESPONSE = DummyResponse()

# the testcases themselves

class TestBug(ZopeTestCase.ZopeTestCase):
    """Test the Bug class
    """
    def afterSetUp(self):
        self.folder._addRole('Customer')
        self.folder.acl_users._addUser('prog_user', 'secret', 'secret', ('Manager',), ())
        self.folder.acl_users._addUser('cust_user', 'secret2', 'secret2', ('Customer',), ())
        '''Add repository to default fixture'''
        dispatcher = self.folder.manage_addProduct['DDBug']
        dispatcher.manage_addBugRepository('repo_en')
        self.repo_en = self.folder['repo_en']
        dispatcher.manage_addBugRepository('repo_pt')
        self.repo_pt = self.folder['repo_pt']
        request = self.app.REQUEST
        #self.bug = self.repo_en.newBug()

    def afterClear(self):
        '''Clean up after myself'''
        try: del self.repo_en
        except AttributeError: pass

    # Test fixture ##################################################

    def testBugFactory(self):
        dummyReq = DummyRequest()
        self.setPermissions([permissions.ADD_BUG])
        dispatcher = self.repo_en.manage_addProduct['DDBug']
        dispatcher.manage_addBug(dummyReq)
        dest = dummyReq.RESPONSE.redirectedTo
        self.failUnlessEqual(dest, self.repo_en.absolute_url() + "/manage_addBugForm")

    def testContainerFilter(self):
        self.failUnless(DDBug.bug.containerFilter(self.repo_en),
                        "repository doesn't pass bug.containerFilter")

    def test_schema(self):
        htmlResult = self.repo_en.MasterBug.schema(isEditForm=1)

    def test_optionsForStatus(self):
        all_status = self.repo_en.MasterBug.optionsForStatus()
        self.failUnless(len(all_status) == 11,
                        "optionsForStatus should be 11: %s" % all_status)

    def test_status(self):
        self.setPermissions([permissions.ADD_BUG])
        aBug = self.repo_en.newBug()
        self.failUnless(aBug.status == "NEW",
                        "getStatus returned invalid status")

    def test_optionsForPriority(self):
        all_priorities = self.repo_en.MasterBug.optionsForPriority()
        self.failUnless(len(all_priorities) == 5,
                        "optionsForPriority() should be 5: %s" % all_priorities)

    def test_admin(self):
        htmlResult = self.repo_en.MasterBug.admin()

    def test_editBug(self):
        self.setPermissions([permissions.ADD_BUG])
        aBug = self.repo_en.newBug()
        aBug.manage_changeProperties(summary='Summary', priority='1', status='NEW')
        
        aBug.manage_editBug(summary='Summary Modified', priority='2', status='ANALISYS')
        
        self.failUnless(aBug.summary == 'Summary Modified', "bug summary not modified")
        self.failUnless(aBug.priority == '2', "bug priority not modified")
        self.failUnless(aBug.status == 'ANALISYS', "bug status not modified")

    def test_editBugWithREQUEST(self):
        self.setPermissions([permissions.ADD_BUG])
        aBug = self.repo_en.newBug()
        aBug.manage_changeProperties(summary='Summary', priority='1', status='NEW')
        REQUEST = self.repo_en.REQUEST
        REQUEST.set('summary', 'Summary Modified')
        REQUEST.set('priority', '2')
        REQUEST.set('status', 'ANALISYS')
        aBug.manage_editBug(REQUEST)
        self.failUnless(aBug.summary == 'Summary Modified', "bug summary not modified")
        self.failUnless(aBug.priority == '2', "bug priority not modified")
        self.failUnless(aBug.status == 'ANALISYS', "bug status not modified")

    def test_getTransitionOptionsAll(self):
        self.setPermissions([permissions.ADD_BUG])
        aBug = self.repo_en.newBug()

        for s in aBug.ALL_STATUS:
          aBug.manage_editBug(status=s)
          transitionMap = aBug.getTransitionOptions()
          nextStatus = [ transition['value'] for transition in transitionMap ]
          if   s == 'NEW':
              assert nextStatus == ["NEW","ANALISYS"], "wrong status!"

          elif s == 'ANALISYS':
              assert nextStatus == ["ANALISYS","FIXING","CLARIFY","DISCARDED", "NON-BUG", "POSTPONED"], "wrong status!"

          elif s == 'CLARIFY':
              assert nextStatus == ["CLARIFY","RE-SENT"], "wrong status!"

          elif s == 'RE-SENT':
              assert nextStatus == ["RE-SENT","ANALISYS"], "wrong status!"

          elif s == 'FIXING':
              assert nextStatus == ["FIXING","FIXED","TESTING"], "wrong status!"

          elif s == 'TESTING':
              assert nextStatus == ["TESTING","FIXING","FIXED"], "wrong status!"

          elif s == 'FIXED':
              assert nextStatus == ["FIXED","APPROVED","RE-SENT"], "wrong status!"

          elif s == 'APPROVED':
              assert nextStatus == ["APPROVED"], "wrong status!"

          elif s == 'DISCARDED':
              assert nextStatus == ["DISCARDED"], "wrong status!"

          elif s == 'NON-BUG':
              assert nextStatus == ["NON-BUG"], "wrong status!"

          elif s == 'POSTPONED':
              assert nextStatus == ["POSTPONED","RE-SENT"], "wrong status!"

    def test_open(self):
        self.setPermissions([permissions.ADD_BUG])
        aBug = self.repo_en.newBug()
        aBug.manage_editBug(status='NEW')
        assert aBug.open()
        
        anotherBug = self.repo_en.newBug()
        anotherBug.manage_editBug(status='APPROVED')
        assert anotherBug.open() == 0

    def test_optionsForSeverity(self):
        all_severities = self.repo_en.MasterBug.optionsForSeverity()
        self.failUnless(len(all_severities) == 5,
                        "optionsForSeverity should be 5: %s" % all_severities)
                        
    def test_properties(self):
        correct_properties = (
            { 'id':'reported_by', 'type':'string', 'mode':'w' },
            { 'id':'summary', 'type':'text', 'mode':'w' },
            { 'id':'status', 'type':'selection', 'mode':'w', 'select_variable':'optionsForStatus' },
            { 'id':'priority', 'type':'selection', 'mode':'w', 'select_variable':'optionsForPriority' },
            { 'id':'severity', 'type':'selection', 'mode':'w', 'select_variable':'optionsForSeverity' },
            { 'id':'error_message', 'type':'text', 'mode':'w' },
            { 'id':'url', 'type':'string', 'mode':'w' },
            { 'id':'browser', 'type':'string', 'mode':'w' },
            { 'id':'steps_to_reproduce', 'type':'text', 'mode':'w' },
            { 'id':'comments', 'type':'text', 'mode':'w' },
            { 'id':'assigned_to', 'type':'string', 'mode':'w' },
            { 'id':'workaround', 'type':'text', 'mode':'w' },
            { 'id':'estimated_time_to_fix', 'type':'int', 'mode':'w' },
            { 'id':'actual_time_to_fix', 'type':'int', 'mode':'w' }
        )

        for c_prop in correct_properties:
            for mb_prop in self.repo_en.MasterBug._properties:
                if c_prop['id'] == mb_prop['id']:
                    lt_c_prop = c_prop.items()
                    lt_c_prop.sort()
                    lt_mb_prop = mb_prop.items()
                    lt_mb_prop.sort()
                    self.assertEquals(lt_c_prop, lt_mb_prop) 
                    
    def test_editableProperty(self):
        # during this test everyone can add bugs
        self.setPermissions([permissions.ADD_BUG])
        # Log in as the testUser
        aBug = self.repo_en.newBug()
        uf = self.folder.acl_users
        testUser = uf.getUserById('cust_user').__of__(uf)
        newSecurityManager(None, testUser)
        assert aBug.editableProperty('priority')
        assert aBug.editableProperty('url')
        assert not aBug.editableProperty('assigned_to')
        assert not aBug.editableProperty('workaround')

        testUser = uf.getUserById('prog_user').__of__(uf)
        newSecurityManager(None, testUser)
        assert not aBug.editableProperty('priority')
        assert aBug.editableProperty('url')
        assert not aBug.editableProperty('assigned_to')
        assert aBug.editableProperty('workaround')

    def test_visibleProperty(self):
        # during this test everyone can add bugs
        self.setPermissions([permissions.ADD_BUG])
        # Log in as the testUser
        aBug = self.repo_en.newBug()
        uf = self.folder.acl_users
        testUser = uf.getUserById('cust_user').__of__(uf)
        newSecurityManager(None, testUser)
        assert aBug.visibleProperty('priority')
        assert aBug.visibleProperty('url')
        assert aBug.visibleProperty('error_message')
        assert not aBug.visibleProperty('workaround')

        testUser = uf.getUserById('prog_user').__of__(uf)
        newSecurityManager(None, testUser)
        assert aBug.visibleProperty('priority')
        assert aBug.visibleProperty('url')
        assert not aBug.visibleProperty('assigned_to')
        aBug.manage_editBug(assigned_to='prog_user')
        assert aBug.visibleProperty('assigned_to')
        assert aBug.visibleProperty('workaround')

    def test_log(self):
        # Log in as the testUserLog
        uf = self.folder.acl_users
        testUserLog = uf.getUserById('prog_user').__of__(uf)
        newSecurityManager(None, testUserLog)
    
        self.setPermissions([permissions.ADD_BUG])
        aBug = self.repo_en.manage_addBug()
        self.failUnless(aBug.listLog()[0][17:] == 'Bug created by prog_user', "Log is not working, the log should be ['Bug criado por prog_user'] but got %s" % aBug.listLog())
        aBug.manage_editBug(status="NEW")
        self.failUnless(len(aBug.listLog()) == 1, "Log is not working, the len of log should be 1")
        aBug.manage_editBug(status="ANALISYS")
        self.failUnless(len(aBug.listLog()) == 2, "Log is not working, the len of log should be 2")

    def test_comments(self):
        uf = self.folder.acl_users
        testUserLog = uf.getUserById('prog_user').__of__(uf)
        newSecurityManager(None, testUserLog)
    
        self.setPermissions([permissions.ADD_BUG])
        aBug = self.repo_en.manage_addBug()
        comments = []
        comments.append("abc")
        aBug.manage_editBug(status="NEW", comments=comments[0])
        comments.append("def")
        aBug.manage_editBug(status="NEW", comments=comments[1])
        i = 0
        for comment in aBug.listComments():
            self.assertEquals(comment[17:], comments[i] + " by prog_user")
            i += 1
        
    def test_getStatusLabel(self):
        # during this test everyone can add bugs
        self.setPermissions([permissions.ADD_BUG])
        # Log in as the testUser
        aBug = self.repo_en.manage_addBug()

        assert aBug.getStatusLabel() == 'New', "Bug status label is wrong."

        for id, label in bug.ALL_STATUS_ITEMS:
            label2 = aBug.getStatusLabel(id)
            assert label2 == label, ("Wrong label for %s: should be %s, but it %s" 
                                     % (id, label, label2))
        
    def test_getPriorityLabel(self):
        # during this test everyone can add bugs
        self.setPermissions([permissions.ADD_BUG])
        # Log in as the testUser
        aBug = self.repo_en.manage_addBug()

        assert aBug.getPriorityLabel() == '5', "Bug priority label is wrong."

        for id in bug.ALL_PRIORITIES:
            id2 = aBug.getPriorityLabel(id)
            assert id2 == id, ("Wrong label for %s: should be %s, but it %s" 
                               % (id, label, label2))
        
    def test_getSeverityLabel(self):
        # during this test everyone can add bugs
        self.setPermissions([permissions.ADD_BUG])
        # Log in as the testUser
        aBug = self.repo_en.manage_addBug()

        assert aBug.getSeverityLabel() == 'Improvement', "Bug severity label is wrong."

        for id, label in bug.ALL_SEVERITIES_ITEMS:
            label2 = aBug.getSeverityLabel(id)
            assert label2 == label, ("Wrong label for %s: should be %s, but it %s" 
                                     % (id, label, label2))
        

        
    def test_Permissions(self):
        self.assertRaises(AccessControl.Unauthorized,
                          self.repo_en.MasterBug.restrictedTraverse, 'manage_editBug')
        self.assertRaises(AccessControl.Unauthorized,
                          self.repo_en.MasterBug.restrictedTraverse, 'admin')
        self.assertRaises(AccessControl.Unauthorized,
                          self.repo_en.restrictedTraverse, 'manage_addBug')

        self.setPermissions([permissions.ADD_BUG])
        try:
            self.repo_en.restrictedTraverse('manage_addBug')
        except AccessControl.Unauthorized:
            self.fail('Could not add Bug: Unauthorized')
        self.setPermissions([permissions.EDIT_BUG])
        try:
            self.repo_en.MasterBug.restrictedTraverse('manage_editBug')
        except AccessControl.Unauthorized:
            self.fail('Could not edit Bug: Unauthorized')

if __name__ == '__main__':
    framework(descriptions=1, verbosity=2)
else:
    import unittest
    def test_suite():
        suite = unittest.TestSuite()
        suite.addTest(unittest.makeSuite(TestBug))
        return suite
